package cn.jy.boot.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
        userDetailsManager.createUser(User.withUsername("root").password("{noop}123").roles("admin").build());
        return userDetailsManager;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    //注入自定义的过滤器
    public LoginFilter loginFilter() throws Exception {
        LoginFilter loginFilter = new LoginFilter();
        //指定认证的地址
        loginFilter.setFilterProcessesUrl("/doLogin");
        loginFilter.setUsernameParameter("uname");
        loginFilter.setPasswordParameter("pwd");
        //认证成功后
        loginFilter.setAuthenticationSuccessHandler((request,response,authentication)->{
            //自定义成功之后返回的信息
            Map<String,Object> returnInfo = new HashMap<>();
            returnInfo.put("msg","登陆成功");
            returnInfo.put("code", HttpStatus.OK.value());
//            returnInfo.put("code","200");
            returnInfo.put("authentication",authentication.getPrincipal());
//        把要返回的信息转化为json字符串
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(returnInfo);
//        把json字符串返回
            response.setContentType("text/json;charset=utf-8");
            response.setStatus(HttpStatus.OK.value());
            response.getWriter().print(json);
        });
        //认证失败后
        loginFilter.setAuthenticationFailureHandler((request,response,exception)->{

            //        自定义认证失败信息
            Map<String,Object> info = new HashMap<>();
            info.put("msg","认证失败");
//            info.put("code","500");
            info.put("exception",exception.getMessage());
//        将认证失败信息转化为json
            String json = new ObjectMapper().writeValueAsString(info);
//        将json响应
            response.setContentType("text/json;charset=utf-8");
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            response.getWriter().print(json);
        });
        //认证异常
        //指定认证管理器
        loginFilter.setAuthenticationManager(authenticationManagerBean());
        return loginFilter;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
//                .antMatchers("/login.html").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
//                .loginPage("/login.html")
//                .loginProcessingUrl("/doLogin")
//                .usernameParameter("uname").passwordParameter("pwd")
                .and()
//                .csrf().disable() //禁用跨站请求伪造的防御
                .csrf()  //开启跨站请求伪造的防御
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
        ;

        http.addFilterAt(loginFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}
